home *** CD-ROM | disk | FTP | other *** search
- /*
- * Yamana's Otomeza Plug-in Tool
- * ぱいろーだ
- *
- * 1995.07.23
- * 1995.07.30 16色に暫定対応
- * 1995.08.06 デフォルトパレットの修正, ビット操作部の改良
- * 1995.08.13 16色の横幅の半端なものの読み込みに対応
- * 1995.08.20 ↑大嘘だったので修正
- *
- * 問題点
- * ・16色画像を256色とみなして処理するので、無駄なメモリを食う。
- *
- *
- * "Pi" (c) A.Yanagisawa
- */
- #include "otome_pi.h"
-
- const char longname[] = "File :Pi ローダ";
- const char extend[] = "PI";
-
- #define USE_FILE PI_LOAD
- #include "otome_pi.c"
-
- typedef
- struct
- { char mode; /* パレットなし= 0x80 */
- char n;
- char m; /* 縦横比 n/m */
- char pix; /* 4 or 8 */
- char name[4]; /* 機種名 */
- short mdat_len; /* 機種予約コードサイズ */
- char *mdat; /* 機種予約コード */
- short x;
- short y;
- char *palt; /* 0 or 3*16 or 3*256 */
- }
- PiHeader;
-
- unsigned int Pi_getBit();
-
- int Pi_countBit = 0;
- int Pi_maxBit;
- char *ColTbl;
-
- int precol;
-
- /********************************************************************/
-
- extern int Pi_getColor256();
- extern int Pi_getColor16();
-
- int Pi_decode( decbuf, buf, head )
- char *decbuf,*buf;
- PiHeader *head;
- {
- int i;
- char c0,c1,c2,c3;
- char *image;
- int pos,len,Width,Height;
- int prepos,Pi_all;
- int (*Pi_getColor)();
-
- int Pi_posTable[][2] =
- { {-2, 0 }, /* 0 :前のピクセルにより変化するので注意 */
- { 0,-1 }, /* 1: 1ライン上 */
- { 0,-2 }, /* 2: 2ライン上 */
- { 1,-1 }, /* 3: 1ライン上の1ドット右 */
- {-1,-1 } /* 4: 1ライン上の1ドット左 */
- };
-
- Width = head->x;
- Height = head->y;
- Pi_all = (Width * (Height+2)) ;
-
- for( i=1; i<=4 ; i++ )
- Pi_posTable[i][0] += Pi_posTable[i][1]*Width;
-
- if( head->pix == 8 ) Pi_getColor = Pi_getColor256;
- else Pi_getColor = Pi_getColor16;
-
- image = decbuf;
- precol = 0;
- c0 = Pi_getColor( buf );
- c1 = Pi_getColor( buf );
-
- for( i=0; i<Width; i++ ) /* 先頭2ラインを先に埋める */
- {
- *image++ = c0;
- *image++ = c1; /* 常に2ドットごと扱う */
- }
-
- prepos = -1;
- while( Pi_countBit < Pi_maxBit )
- {
- /* まず位置データを得る。2 or 3 ビット長 */
- pos = Pi_getBit( buf, 2 );
- if( pos == 3 ) pos += Pi_getBit( buf, 1 );
-
- /* 位置が前に記録した位置と同じとき */
- if( pos == prepos )
- { do
- { *image++ = Pi_getColor( buf );
- *image++ = Pi_getColor( buf );
-
- }while( Pi_getBit(buf,1) ); /* (7) 'b' 同じパターンがない限り */
-
- prepos = -1;
- continue;
- }
- prepos = pos;
-
- /* (4') 長さを求める */
- len = Pi_getLen(buf);
-
- /* (3) */
- if( pos ) /* pos==(1~4) */
- {
- if( pos>4 ) break;
-
- memcpy( image, image + Pi_posTable[pos][0], len*2 );
- image += len*2 ;
- }
- else /* pos==0 : 直前色と同じなら2,違うとき4ドット右 */
- {
- c1 = *(image-2);
- c0 = *(image-1);
-
- if ( c0 == c1 )
- { while( len-- ) /* 同じパターンが続く限り繰り返す */
- {
- *image++ = c0;
- *image++ = c0;
- }
- }else
- { c3 = *(image-4);
- c2 = *(image-3);
-
- while( len-- )
- {
- *image++ = c3;
- *image++ = c2;
- if( (len--) <= 0 ) break; /* 2ドット単位 */
- *image++ = c1;
- *image++ = c0;
- }
- }
-
- }/* (3) */
-
- precol = *(image-1);
-
- }/* LOOP */
-
-
- return NOERR;
- }
-
- /**************************************/
- /* 0 1
- 10x 2-3
- 110xx 4-7
- 1110xxx 8-15
- 11110xxxx 16-31
- : :
- */
- int Pi_getLen(buf) /* 長さ符号の解析 */
- char *buf;
- {
- int i;
-
- for( i=0; Pi_getBit(buf,1) ; i++ );
-
- if( i==0 ) return 1;
-
- return (Pi_getBit(buf,i) | (1<<i));
-
- }
-
- /* 任意ビット長のデータを返す */
- unsigned int Pi_getBit( buf,bit )
- char *buf;
- int bit;
- {
- char restBit[]= { 0xff,0x7f,0x3f,0x1f,0x0f,0x07,0x03,0x01 };
- register unsigned int rest,low;
-
- if( Pi_countBit+bit >= Pi_maxBit )
- { Pi_countBit += bit;
- return 0;
- }
- rest = (buf[ (Pi_countBit>>3) ] & restBit[ (Pi_countBit & 7) ]);
- low = (8 - (Pi_countBit & 7) );
-
- while( bit > low ) /* 足りないときは追加する */
- {
- rest = (rest<<8) | buf[ (Pi_countBit>>3)+1 ];
- low += 8;
- }
- Pi_countBit += bit ;
-
- return (rest >>(low-bit) );
- }
-
-
- /**************************************/
-
- int Pi_getColor256( buf )
- char *buf;
- {
- register unsigned int col;
- char *p;
-
- if( Pi_getBit(buf,1) ) col = Pi_getBit(buf,1) ;
- else if( Pi_getBit(buf,1) == 0 ) col = Pi_getBit(buf,1) | 0x02 ;
- else if( Pi_getBit(buf,1) == 0 ) col = Pi_getBit(buf,2) | 0x04 ;
- else if( Pi_getBit(buf,1) == 0 ) col = Pi_getBit(buf,3) | 0x08 ;
- else if( Pi_getBit(buf,1) == 0 ) col = Pi_getBit(buf,4) | 0x10 ;
- else if( Pi_getBit(buf,1) == 0 ) col = Pi_getBit(buf,5) | 0x20 ;
- else if( Pi_getBit(buf,1) == 0 ) col = Pi_getBit(buf,6) | 0x40 ;
- else col = Pi_getBit(buf,7) | 0x80 ;
-
- col &= 0xff;
-
- /* 色テーブルのシフト */
- p = ColTbl+ precol*256 + col ;
- precol = *p;
-
- for( ; col ; col--,p-- )
- *p = *(p-1);
- *p = precol;
-
- return precol;
- }
-
- int Pi_getColor16( buf )
- char *buf;
- {
- register unsigned int col;
- char *p;
-
- if( Pi_getBit(buf,1) == 1 ) col = Pi_getBit(buf,1) ;
- else if( Pi_getBit(buf,1) == 0 ) col = Pi_getBit(buf,1) | 2 ;
- else if( Pi_getBit(buf,1) == 0 ) col = Pi_getBit(buf,2) | 4 ;
- else col = Pi_getBit(buf,3) | 8 ;
-
- /* 色テーブルのシフト */
-
- p = ColTbl + precol*16 + col ;
- precol = *p ;
- for( ; col>0 ; col--,p-- )
- *p = *(p-1);
- *p = precol;
-
- return precol;
- }
-
- void Pi_initColorTable(col)
- int col;
- {
- int i, j;
-
- for( i=0; i<col; i++ )
- for( j=0; j<col; j++ )
- ColTbl[ j + i*col ] = ((i + col-j) & (col-1));
-
- }
- /*
- 0fedcba987654321
- 10fedcba98765432
- 210fedcba9876543
- :
- */
-
- /**************************************/
-
-
- int Pi_readHeader( head, fp )
- PiHeader *head;
- FILE *fp;
- {
- int i=0;
-
- if( fgetc(fp)!= 'P' || fgetc(fp)!= 'i' )
- return ERROR;
-
- while( fgetc(fp) != 0x1a && ferror(fp)==0 );
- while( fgetc(fp) != 0x00 && ferror(fp)==0 );
- if( ferror(fp) ) return ERROR;
-
- head->mode = (char)fgetc( fp );
- head->n = (char)fgetc( fp );
- head->m = (char)fgetc( fp );
- head->pix = (char)fgetc( fp );
-
- fread( head->name ,1,4 ,fp );
-
- head->mdat_len = (fgetc( fp )<<8) + (char)fgetc( fp );
- for( i=0; i< head->mdat_len ; i++ )
- fgetc( fp );
-
- head->x = (short)(fgetc( fp )<<8 | (char)fgetc( fp ) );
- head->y = (short)(fgetc( fp )<<8 | (char)fgetc( fp ) );
-
- // printf("(x,y)=(%d,%d),pix=%d\r\n",head->x,head->y,head->pix);
-
- return ferror(fp);
- }
-
-
- long getFileSize( fp )
- FILE *fp;
- {
- unsigned long from,to;
-
- from = ftell(fp);
- fseek( fp, 0, SEEK_END );
- to = ftell(fp);
- fseek( fp, from, SEEK_SET );
-
- return (to-from);
- }
-
- /*******************************************************************/
-
- void Pi_setPalette( pal, col, fp )
- char *pal;
- int col;
- FILE *fp;
- {
- int i,j;
-
- DWORD( pal ) = col;
- for( i=0,j=4; i<col; i++,j+=8 )
- {
- WORD( pal+j ) = i ;
- pal[ j+5 ] = (char)fgetc( fp ); /* R */
- pal[ j+6 ] = (char)fgetc( fp ); /* G */
- pal[ j+4 ] = (char)fgetc( fp ); /* B */
- }
-
- }
-
- void Pi_setDefaultPalette( pal,col )
- char *pal;
- int col;
- {
- int i,j;
-
- DWORD( pal ) = col;
-
- if( col==16 ) /* TOWNSのdefaultと同じ */
- for( i=0,j=4; i<16; i++,j+=8 )
- { WORD( pal+ j ) = (unsigned short)i;
-
- pal[ j+5 ] = (i & 2) * ( ((i & 8) | 7 )<<3 );
- pal[ j+6 ] = (i & 4) * ( ((i & 8) | 7 )<<2 );
- pal[ j+4 ] = (i & 1) * ( ((i & 8) | 7 )<<4 );
- }
- else /* TOWNSのdefaultよりちょっと暗い */
- for( i=0,j=4; i<256; i++,j+=8 )
- { WORD( pal+ j ) = (unsigned short)i;
-
- pal[ j+5 ] = (((i>>2 ) & 7) << 5); /* R */
- pal[ j+6 ] = (((i>>5 ) & 7) << 5); /* G */
- pal[ j+4 ] = (( i & 3) << 6); /* B */
- }
-
- }
-
-
-
- /*******************************************************************/
- /** プラグイン呼び出し **/
-
- #define FNAME (pi_data->fname)
-
- int APL_exec()
- {
- FILE *fp;
- char *buf,*mem, *pal,*image;
- int col;
- long l;
- PiHeader head;
-
- if( (fp = fopen( FNAME , "rb" )) == NULL )
- return PI_ERROR_FILE_OPEN;
-
- /** ヘッダ読み込み **/
- if( Pi_readHeader( &head, fp ) )
- { fclose( fp );
- return ERROR;
- }
- // printf("size=(%d,%d)", head.x, head.y );
-
-
- if( head.pix > pi_imge->pix ) /* 減色処理などはしない */
- return ERROR;
-
- if( head.pix < 8 ) col = 16;
- else col = 256;
-
- /** パレット情報読み取り **/
- if( (pal=(char*)PI_MALLOC( 4+col*8 ))==NULL )
- { fclose( fp );
- return PI_ERROR_NO_MEMORY;
- }
-
- if( head.mode & 0x80 ) /* パレットなし */
- Pi_setDefaultPalette( pal,col );
- else
- Pi_setPalette( pal, col, fp );
-
- /***/
- if( (l=getFileSize(fp))< 0
- || (mem=(char *)PI_MALLOC( l + col*col ))==NULL )
- { fclose(fp);
- PI_FREE( pal );
- return PI_ERROR_NO_MEMORY;
- }
- buf = mem;
- ColTbl = mem+l;
- Pi_initColorTable( col );
-
- if( fread( buf, 1, l, fp )< l ) /* 一気に読み込み */
- { fclose(fp);
- PI_FREE( pal );
- PI_FREE( mem );
- return PI_ERROR_FILE_OPEN;
- }
- fclose( fp );
- /***/
-
- Pi_maxBit = l*8;
-
- /*** 展開用メモリ確保 **********************************************/
- /* 16色モードの場合横16ドット単位、256色モードの場合横32ドット単位 */
- /* でメモリを確保し、乙女座に渡さなくてはならない。 */
- /********************************************************************/
-
- /* 256色として展開する */
- if( (image=PI_MALLOC( ((head.x+31) & 0xffe0) * (head.y+2)+32 ))==NULL )
- {
- PI_FREE( pal );
- PI_FREE( mem );
- return PI_ERROR_NO_MEMORY;
- }
- #if 1
- /** データ展開 **/
- if( Pi_decode( image, buf, &head ) )
- {
- PI_FREE( pal );
- PI_FREE( mem );
-
- return ERROR;
- }
- #endif
-
- PI_FREE(mem);
-
- pi_imge->image = image;
- pi_imge->clut = pal;
- pi_imge->pix = head.pix;
- pi_imge->size.x = head.x ;
- pi_imge->size.y = head.y ;
-
- if( head.pix == 8 ) conv_vram256( image, &head );
- if( head.pix == 4 ) conv_vram16 ( image, &head );
-
- return NOERR;
- }
-
-
-
- /***** 展開したバッファを TOWNS の VRAM に合うよう変換する *****/
-
- void conv_vram( image, head )
- char *image;
- PiHeader *head;
- {
- int Width = (head->x+31)& 0xffe0 ;
- int y;
- char *p = image + head->x * 2 ;
-
- for( y=head->y-1; y>0 ; y-=2 )
- { _rmemcpy( p+Width*(y ), p+head->x*(y ), head->x );
- _rmemcpy( p+Width*(y-1), p+head->x*(y-1), head->x );
- }
- if( y==0 )
- _rmemcpy( p+Width*(0 ), p+head->x*(0 ), head->x );
-
- }
-
- int conv_vram256( char *image,PiHeader *head )
- {
- int Width;
-
- Width = (head->x +31)& 0xffe0; /* 256色の場合は32ドット単位 */
-
- if( Width != head->x )
- conv_vram( image, head );
-
- /* 上 2 ラインは必要ない */
- memcpy( image, image+(head->x*2), (Width*head->y) );
-
- return NOERR;
- }
-
- int conv_vram16( char *image,PiHeader *head )
- {
- int x,y,Width;
- char *p,*pp;
-
- Width = (head->x+31)& 0xffe0; /* 16色は横16ドット単位 */
-
- if( head->x != Width )
- conv_vram( image, head );
-
- p = image + head->x*2 ;
- pp= image ;
- for( y=0 ; y<head->y ; y++ )
- {
- for(x=0; x< Width ; x+=8 ) /* ループ展開すれば少しは速い? */
- { *pp++ = (*p++ & 0x0f) | (*p++ & 0x0f)<<4 ;
- *pp++ = (*p++ & 0x0f) | (*p++ & 0x0f)<<4 ;
- *pp++ = (*p++ & 0x0f) | (*p++ & 0x0f)<<4 ;
- *pp++ = (*p++ & 0x0f) | (*p++ & 0x0f)<<4 ;
- }
- }
- return NOERR;
- }
-
-